home *** CD-ROM | disk | FTP | other *** search
- /*
-
-
- © Copyright 1991 Ricardo Batista, All Rights Reserved.
-
-
- Sprite Manager
-
-
- 04/20/91
-
-
- HISTORY: (Most Recent first)
-
-
- 04/20/91 rb New today
-
-
- */
-
-
-
-
- #include <Types.h>
- #include <QuickDraw.h>
- #include <QDOffscreen.h>
- #include <Memory.h>
- #include <Resources.h>
- #include <OSUtils.h>
- #include <Retrace.h>
- #include <Windows.h>
- #include <ToolUtils.h>
-
- #include "SpriteMgr.h"
-
- #define desiredPixSize 8
-
- SpriteMgrRecPtr Sprite_Mgr_Globals; // global used to save our information
-
-
- pascal short SetDepth(GDHandle gd, short newDepth, short whichFlags, short newFlags) =
- {0x203C, 0x000A, 0x0013, 0xAAA2};
-
- pascal short HasDepth(GDHandle gd, short newDepth, short whichFlags, short newFlags) =
- {0x203C, 0x000A, 0x0014, 0xAAA2};
-
-
-
-
-
- /*
- This routine initializes the sprite manager, it must be called after dialogs,
- windows, resources, and quickdraw have been initialized. This routine creates
- a record to memory to keep the sprite manager globals, it also finds the best
- monitor in which to display the color animation and sets the monitor to 4 bit
- color after saving the previous color depth. This routine also installs a small
- vbl task used by the drawing routines.
- if cTable is not nil the given color table is made the current color table and the
- previous color table saved for later restoration.
- returns 0 if no error occured. 1 if no color monitor present or not enough memory
- to create memory record.
- */
-
- short InitSpriteMgr(CTabHandle cTable)
- {
- short err;
- GDHandle device;
- PixMapHandle pixH;
- Boolean done = false;
- short oldPixelSize;
- CTabHandle colorTable = 0L;
- short mode;
-
- if (Sprite_Mgr_Globals)
- return(0);
- Sprite_Mgr_Globals = (SpriteMgrRecPtr) NewPtrClear(sizeof(SpriteMgrRec));
- if (!Sprite_Mgr_Globals)
- return(1);
- device = GetDeviceList();
- if (!device) {
- DisposPtr((Ptr) Sprite_Mgr_Globals);
- Sprite_Mgr_Globals = 0L;
- return(1);
- }
- while (device && !done) {
- pixH = (**device).gdPMap;
- oldPixelSize = (**pixH).pixelSize;
- if (oldPixelSize == desiredPixSize) {
- if (cTable) {
- colorTable = (**pixH).pmTable;
- (**pixH).pmTable = cTable;
- GDeviceChanged(device);
- }
- done = true;
- }
- else {
- mode = HasDepth(device, desiredPixSize, 1, 1); /* color device */
- if (mode) {
- err = SetDepth(device, desiredPixSize, 1, 1);
- if (cTable) {
- colorTable = (**pixH).pmTable;
- (**pixH).pmTable = cTable;
- GDeviceChanged(device);
- }
- done = true;
- }
- }
- if (!done)
- device = (GDHandle) (**device).gdNextGD;
- }
- if (!done)
- return(1);
-
- Sprite_Mgr_Globals->originalCTable = colorTable;
- Sprite_Mgr_Globals->currCTable = cTable;
- Sprite_Mgr_Globals->originalDepth = oldPixelSize;
- Sprite_Mgr_Globals->task.qType = vType;
- Sprite_Mgr_Globals->task.vblAddr = (ProcPtr) VTASK;
- Sprite_Mgr_Globals->task.vblCount = 1;
- Sprite_Mgr_Globals->task.vblPhase = 0;
- Sprite_Mgr_Globals->deviceUsed = device;
- Sprite_Mgr_Globals->active = false;
- Sprite_Mgr_Globals->changed = true;
- Sprite_Mgr_Globals->updateRects = 0;
-
- err = VInstall((QElemPtr) &Sprite_Mgr_Globals->task.qLink);
- return(err);
- }
-
-
-
-
-
-
-
-
-
-
-
- /*
- This routine disposes of the window used by animation, destroys all of the graphic
- worlds created and deinstalls the vbl task. It also re-enables any applications
- hidden by ActivateAnimation.
- Restores the color table if it had been changed when InitSpriteMgr was called.
- This routine should be called when the application quits.
- */
-
- void CloseSpriteMgr(void)
- {
- CTabHandle cTable;
- GDHandle device;
- short err;
-
- VRemove((QElemPtr) &Sprite_Mgr_Globals->task.qLink);
- device = Sprite_Mgr_Globals->deviceUsed;
- if (Sprite_Mgr_Globals->originalCTable) {
- cTable = (**(**device).gdPMap).pmTable;
- (**(**device).gdPMap).pmTable = Sprite_Mgr_Globals->originalCTable;
- GDeviceChanged(device);
- DisposHandle((Handle) cTable);
- }
- err = SetDepth(device, Sprite_Mgr_Globals->originalDepth, 1, 1);
-
- while (Sprite_Mgr_Globals->backSprites)
- KillSprite(Sprite_Mgr_Globals->backSprites->id);
- while (Sprite_Mgr_Globals->normSprites)
- KillSprite(Sprite_Mgr_Globals->normSprites->id);
- while (Sprite_Mgr_Globals->foreSprites)
- KillSprite(Sprite_Mgr_Globals->foreSprites->id);
-
- while (Sprite_Mgr_Globals->backgrounds)
- KillBackground(Sprite_Mgr_Globals->backgrounds->id);
- while (Sprite_Mgr_Globals->foregrounds)
- KillForeground(Sprite_Mgr_Globals->foregrounds->id);
-
- if (Sprite_Mgr_Globals->animationWindow)
- DisposeWindow((WindowPtr) Sprite_Mgr_Globals->animationWindow);
- if (Sprite_Mgr_Globals->animationGWorld)
- DisposeGWorld(Sprite_Mgr_Globals->animationGWorld);
- if (Sprite_Mgr_Globals->currCTable)
- DisposHandle((Handle) Sprite_Mgr_Globals->currCTable);
- DisposPtr((Ptr) Sprite_Mgr_Globals);
- Sprite_Mgr_Globals = 0L;
- }
-
-
-
-
-
-
- /*
- This routine creates a new background by creating a new graphics world and drawing
- in it the picture with id pictID. drawOrder is the background drawing priority
- with 1 being the highest priority. The highest priority gets drawn first. copyMode
- should be srcCopy for the highest priority element and transparent for the rest.
- animationRect is the area within the animation screen where the background will be
- drawn. The size of the picture must be at least as big as the animationRect and can
- be bigger if the area is to be scrolled later in the animation. If the given pictID
- is already in use by another graphic entity then graphics world will be shared instead
- of creating a new graphics world.
- id is returned if no errors occur. Otherwise 0 if there was not enough memory for the
- offscreen world or the picture could not be loaded.
- */
-
-
-
- short NewBackground(short pictID, short drawOrder, short copyMode, Rect *animationRect, short id)
- {
- return (NewScenery(pictID, drawOrder, copyMode, animationRect, id, true));
- }
-
-
-
-
-
-
-
-
-
-
- /*
- This routine creates a new foreground by creating a new graphics world and drawing
- in it the picture with id pictID. drawOrder is the foreground drawing priority
- with 1 being the highest priority. The highest priority gets drawn first. copyMode
- should be transparent in most cases.
- animationRect is the area within the animation screen where the foreground will be
- drawn. The size of the picture must be at least as big as the animationRect and can
- be bigger if the area is to be scrolled later in the animation. If the given pictID
- is already in use by another graphic entity then graphics world will be shared instead
- of creating a new graphics world.
- id is returned if no errors occur. Otherwise 0 if there was not enough memory for the
- offscreen world or the picture could not be loaded.
- */
-
-
-
- short NewForeground(short pictID, short drawOrder, short copyMode, Rect *animationRect, short id)
- {
- return (NewScenery(pictID, drawOrder, copyMode, animationRect, id, true));
- }
-
-
-
-
-
- /*
- This routine changes the offsets where the image is to be drawn in the animation
- world and marks the background as changed so that is it redrawn again.
- */
-
-
-
- void ScrollBackground(short id, short vOffset, short hOffset)
- {
- SceneryInfoRecPtr sc;
-
- sc = Sprite_Mgr_Globals->backgrounds;
- while (sc) {
- if (sc->id == id) {
- sc->scrollOffset.v += vOffset;
- sc->scrollOffset.h += hOffset;
- sc->changed = true;
- return;
- }
- sc = (SceneryInfoRecPtr) sc->nextScenery;
- }
- }
-
-
-
-
-
-
-
-
-
- /*
- This routine changes the offsets where the image is to be drawn in the animation
- world and marks the foreground as changed so that is it redrawn again.
- */
-
-
- void ScrollForeground(short id, short vOffset, short hOffset)
- {
- SceneryInfoRecPtr sc;
-
- sc = Sprite_Mgr_Globals->foregrounds;
- while (sc) {
- if (sc->id == id) {
- sc->scrollOffset.v += vOffset;
- sc->scrollOffset.h += hOffset;
- sc->changed = true;
- return;
- }
- sc = (SceneryInfoRecPtr) sc->nextScenery;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
- /*
- This routine sets an auto scroll timer and amount for a background to
- be scrolled automatically. Autoscrolling has some limitations at the
- time.
- */
-
- void AutoScrollBackground(short id, short vOffset, short hOffset, long scrollTicks)
- {
- SceneryInfoRecPtr sc;
-
- sc = Sprite_Mgr_Globals->backgrounds;
- while (sc) {
- if (sc->id == id) {
- sc->nextTickCount = TickCount() + scrollTicks;
- sc->scrollTicks = scrollTicks;
- sc->autoScrollAmount.v = vOffset;
- sc->autoScrollAmount.h = hOffset;
- return;
- }
- sc = (SceneryInfoRecPtr) sc->nextScenery;
- }
- }
-
-
-
-
-
-
-
-
-
- /*
- This routine sets an auto scroll timer and amount for a foreground to
- be scrolled automatically. Autoscrolling has some limitations at the
- time.
- */
-
- void AutoScrollForeground(short id, short vOffset, short hOffset, long scrollTicks)
- {
- SceneryInfoRecPtr sc;
-
- sc = Sprite_Mgr_Globals->foregrounds;
- while (sc) {
- if (sc->id == id) {
- sc->nextTickCount = TickCount() + scrollTicks;
- sc->scrollTicks = scrollTicks;
- sc->autoScrollAmount.v = vOffset;
- sc->autoScrollAmount.h = hOffset;
- return;
- }
- sc = (SceneryInfoRecPtr) sc->nextScenery;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
- /*
- This routine disposes of the graphics world used by the graphic entity with
- id number id if the graphics world is not being shared by other graphic entities.
- It also deletes any information about this entity from the Sprite Manager
- animation record.
- */
-
-
-
- void KillBackground(short id)
- {
- SceneryInfoRecPtr sc, sc2;
-
- sc = Sprite_Mgr_Globals->backgrounds;
- if (sc && (sc->id == id)) {
- Sprite_Mgr_Globals->backgrounds = (SceneryInfoRecPtr)
- sc->nextScenery;
- if (sc->shared) {
- sc2 = FindTwinScenery(sc->pictID);
- if (sc2)
- sc->sceneryWorld = 0L;
- }
- if (sc->sceneryWorld)
- DisposeGWorld(sc->sceneryWorld);
- DisposPtr((Ptr) sc);
- return;
- }
- sc2 = sc;
- sc = (SceneryInfoRecPtr) sc2->nextScenery;
- while (sc) {
- if (sc->id == id) {
- sc2->nextScenery = sc->nextScenery;
- if (sc->shared) {
- sc2 = FindTwinScenery(sc->pictID);
- if (sc2)
- sc->sceneryWorld = 0L;
- }
- if (sc->sceneryWorld)
- DisposeGWorld(sc->sceneryWorld);
- DisposPtr((Ptr) sc);
- return;
- }
- sc2 = sc;
- if (sc)
- sc = (SceneryInfoRecPtr) sc->nextScenery;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
- /*
- This routine disposes of the graphics world used by the graphic entity with
- id number id if the graphics world is not being shared by other graphic entities.
- It also deletes any information about this entity from the Sprite Manager
- animation record.
- */
-
-
- void KillForeground(short id)
- {
- SceneryInfoRecPtr sc, sc2;
-
- sc = Sprite_Mgr_Globals->foregrounds;
- if (sc && (sc->id == id)) {
- Sprite_Mgr_Globals->foregrounds = (SceneryInfoRecPtr)
- sc->nextScenery;
- if (sc->shared) {
- sc2 = FindTwinScenery(sc->pictID);
- if (sc2)
- sc->sceneryWorld = 0L;
- }
- if (sc->sceneryWorld)
- DisposeGWorld(sc->sceneryWorld);
- DisposPtr((Ptr) sc);
- return;
- }
- sc2 = sc;
- sc = (SceneryInfoRecPtr) sc2->nextScenery;
- while (sc) {
- if (sc->id == id) {
- sc2->nextScenery = sc->nextScenery;
- if (sc->shared) {
- sc2 = FindTwinScenery(sc->pictID);
- if (sc2)
- sc->sceneryWorld = 0L;
- }
- if (sc->sceneryWorld)
- DisposeGWorld(sc->sceneryWorld);
- DisposPtr((Ptr) sc);
- return;
- }
- sc2 = sc;
- if (sc)
- sc = (SceneryInfoRecPtr) sc->nextScenery;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- /*
- This routine creates a graphics world for the new sprite. If the same pictID is
- shared by another sprite then the graphics world will be shared between all the
- sprites that share the same picture. Otherwise the picture range from pictID to
- pictID + totalPicts will be drawn in the new graphics world. copyMode should be
- transparent in most cases but could be blend in some cases. spriteProc is a
- procedure pointer that if given can be called every ProcTicks ticks
- (sixthieths of a second). If ProcTicks is not zero and spriteProc is nil then
- the Sprite Manager will automatically change the current face of the sprite
- every ProcTicks ticks to the next face. drawOrder is the priority in which the
- sprite will be drawn with 1 being the highest priority. collisionProc is a procedure
- pointer that will be called when a collision with another sprite is detected only if
- the parameter canColide is set to true and the collision occurs with another sprite.
- id is the id number that will be used to identify this sprite.
-
-
- Parameters to the collisionProc are the id of the sprite that collided with this
- sprite.
-
- pascal void CollisionProc(short spriteID);
-
- Parameters to the sprite procedure are the id of the sprite and the rectangle which
- encloses the sprite in the animation world.
-
- pascal void SpriteProc(short spriteID, Rect *locationRect);
- */
-
-
- short NewBackgroundSprite(short pictID, short totalPicts, short copyMode,
- ProcPtr spriteProc, long ProcTicks, short drawOrder,
- ProcPtr collisionProc, Boolean canColide, short id)
- {
- return (SMgrNewSprite(pictID, totalPicts, copyMode, spriteProc, ProcTicks, drawOrder,
- collisionProc, canColide, id, 1));
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- /*
- This routine creates a graphics world for the new sprite. If the same pictID is
- shared by another sprite then the graphics world will be shared between all the
- sprites that share the same picture. Otherwise the picture range from pictID to
- pictID + totalPicts will be drawn in the new graphics world. copyMode should be
- transparent in most cases but could be blend in some cases. spriteProc is a
- procedure pointer that if given can be called every ProcTicks ticks
- (sixthieths of a second). If ProcTicks is not zero and spriteProc is nil then
- the Sprite Manager will automatically change the current face of the sprite
- every ProcTicks ticks to the next face. drawOrder is the priority in which the
- sprite will be drawn with 1 being the highest priority. collisionProc is a procedure
- pointer that will be called when a collision with another sprite is detected only if
- the parameter canColide is set to true and the collision occurs with another sprite.
- id is the id number that will be used to identify this sprite.
-
-
- Parameters to the collisionProc are the id of the sprite that collided with this
- sprite.
-
- pascal void CollisionProc(short spriteID);
-
- Parameters to the sprite procedure are the id of the sprite and the rectangle which
- encloses the sprite in the animation world.
-
- pascal void SpriteProc(short spriteID, Rect *locationRect);
- */
-
-
- short NewSprite(short pictID, short totalPicts, short copyMode,
- ProcPtr spriteProc, long ProcTicks, short drawOrder,
- ProcPtr collisionProc, Boolean canColide, short id)
- {
- return (SMgrNewSprite(pictID, totalPicts, copyMode, spriteProc, ProcTicks, drawOrder,
- collisionProc, canColide, id, 2));
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- /*
- This routine creates a graphics world for the new sprite. If the same pictID is
- shared by another sprite then the graphics world will be shared between all the
- sprites that share the same picture. Otherwise the picture range from pictID to
- pictID + totalPicts will be drawn in the new graphics world. copyMode should be
- transparent in most cases but could be blend in some cases. spriteProc is a
- procedure pointer that if given can be called every ProcTicks ticks
- (sixthieths of a second). If ProcTicks is not zero and spriteProc is nil then
- the Sprite Manager will automatically change the current face of the sprite
- every ProcTicks ticks to the next face. drawOrder is the priority in which the
- sprite will be drawn with 1 being the highest priority. collisionProc is a procedure
- pointer that will be called when a collision with another sprite is detected only if
- the parameter canColide is set to true and the collision occurs with another sprite.
- id is the id number that will be used to identify this sprite.
-
-
- Parameters to the collisionProc are the id of the sprite that collided with this
- sprite.
-
- pascal void CollisionProc(short spriteID);
-
- Parameters to the sprite procedure are the id of the sprite and the rectangle which
- encloses the sprite in the animation world.
-
- pascal void SpriteProc(short spriteID, Rect *locationRect);
- */
-
- short NewForegroundSprite(short pictID, short totalPicts, short copyMode,
- ProcPtr spriteProc, long ProcTicks, short drawOrder,
- ProcPtr collisionProc, Boolean canColide, short id)
- {
- return (SMgrNewSprite(pictID, totalPicts, copyMode, spriteProc, ProcTicks, drawOrder,
- collisionProc, canColide, id, 3));
- }
-
-
-
-
-
-
-
-
-
-
-
-
- /*
- This procedure creates a new animation world and creates a graphics world
- for it. animationRect is the rectangle which will be used for the animation
- in a window to be created by this procedure. The window will be created in the
- graphics device which supports 4 bit color. windowH is the width of the window
- to be created and windowV is the height of the window. wTitle is the title that
- will be given to the window. The window created will be centered in the graphics
- device. A color window pointer is returned to the caller so that the application
- can use the areas outside the animationRect for purposes other than animation such
- as scores.
- */
-
-
-
-
- CWindowPtr NewAnimation(Rect *animationRect, short windowH, short windowV, Str255 wTitle)
- {
- Rect box;
- short err;
- GWorldPtr world = 0L;
- CTabHandle cTable;
- short offsetV, offsetH;
- CGrafPtr savedGWorld;
- GDHandle savedGD;
-
- GetGWorld(&savedGWorld, &savedGD);
- box = (**(Sprite_Mgr_Globals->deviceUsed)).gdRect;
- offsetV = box.bottom - box.top - windowV;
- offsetH = box.right - box.left - windowH;
- if (offsetV > 0)
- offsetV /= 2;
- else
- offsetV = 0;
- if (offsetH > 0)
- offsetH /= 2;
- else
- offsetH = 0;
- box.right = box.left + windowH + offsetH;
- box.bottom = box.top + windowV + offsetV;
- box.top += offsetV;
- box.left += offsetH;
- Sprite_Mgr_Globals->animationWindow = (CWindowPtr) NewCWindow(0L, &box, wTitle,
- true, documentProc, (WindowPtr) -1L, false, 'Anim');
- Sprite_Mgr_Globals->animationRect = *animationRect;
- cTable = Sprite_Mgr_Globals->currCTable;
- err = NewGWorld(&world, desiredPixSize, animationRect, cTable, 0L, (long) useTempMem);
- if (!err) {
- SetGWorld(world, 0L);
- EraseRect(animationRect);
- }
- Sprite_Mgr_Globals->animationGWorld = world;
- if (!world) {
- DisposeWindow((WindowPtr) Sprite_Mgr_Globals->animationWindow);
- Sprite_Mgr_Globals->animationWindow = 0L;
- }
- SetGWorld(savedGWorld, savedGD);
- return(Sprite_Mgr_Globals->animationWindow);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- /*
- This procedure set the current face of the sprite with id number id to the
- given index. The changed flag is set to true so that drawing is performed in
- the next chance by the Sprite Manager.
- */
-
-
-
- void SetCurrentSpriteIndex(short id, short index)
- {
- SpriteInfoRecPtr p;
-
- p = FindSprite(id);
- if (p) {
- p->changed = true;
- p->currentFace = index;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- /*
- This procedure puts the sprite in the animation world at the location given
- by top and left. The changed flag is set to true so that drawing is performed
- as soon as possible. A sprite should only be "put" in the animation world
- once unless it is first "removed" by calling RemoveSprite.
- */
-
- void PutSprite(short id, short top, short left)
- {
- SpriteInfoRecPtr p;
-
- p = FindSprite(id);
- if (p) {
- p->changed = true;
- p->animationRect = p->spriteRect;
- p->animationRect.top += top;
- p->animationRect.bottom += top;
- p->animationRect.left += left;
- p->animationRect.right += left;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- /*
- This procedure removes a sprite from the animation world by setting its
- animation rectangle to an empty rectangle and setting the sprite's changed
- flag so that the animation world is updated correctly.
- */
-
- void RemoveSprite(short id)
- {
- SpriteInfoRecPtr p;
-
- p = FindSprite(id);
- if (p) {
- p->changed = true;
- p->animationRect.top = p->animationRect.left =
- p->animationRect.bottom = p->animationRect.right = 0;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- /*
- This procedure moves the sprite in the animation world first remembering the
- sprite's old location for further updating. The sprite's location is offset by
- h and v. A new face for the sprite can be given by newIndex if newIndex is not
- zero. Once a sprite is "put" in the animation world it should
- */
-
-
- void MoveSprite(short id, short h, short v, short newIndex)
- {
- SpriteInfoRecPtr p;
-
- p = FindSprite(id);
- if (p) {
- p->changed = true;
- p->oldAnimationRect = p->animationRect;
- p->animationRect.top += v;
- p->animationRect.left += h;
- p->animationRect.bottom += v;
- p->animationRect.right += h;
- if (newIndex)
- p->currentFace = newIndex;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- /*
- This procedure moves a sprite with the given id to the location specified by h
- and v. A new face for thr sprite may be given by specifying a newIndex other
- than zero. The old location of the sprite is recorded for further updating.
- */
-
-
-
- void MoveSpriteTo(short id, short h, short v, short newIndex)
- {
- SpriteInfoRecPtr p;
-
- p = FindSprite(id);
- if (p) {
- p->changed = true;
- p->oldAnimationRect = p->animationRect;
- p->animationRect = p->spriteRect;
- p->animationRect.top += v;
- p->animationRect.left += h;
- p->animationRect.bottom += v;
- p->animationRect.right += h;
- if (newIndex)
- p->currentFace = newIndex;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- /*
- This procedure makes visible or invisible a sprite based on the show parameter.
- A "hiden" sprite is not drawn in the animation world but can still create
- collisions if its collision attribute is enabled. If the new visibility state
- of the sprite is changed the "changed" attribute gets set to true so that the
- animation world is updated correctly.
- */
-
-
-
- void ShowSprite(short id, Boolean show)
- {
- SpriteInfoRecPtr p;
-
- p = FindSprite(id);
- if (p) {
- if (show != p->hidden) {
- p->changed = true;
- p->oldAnimationRect = p->animationRect;
- p->hidden = show;
- }
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- /*
- This procedure returns the current location of the given sprite in the animation
- world or an empty rectangle if the sprite is not currently in the animation world.
- More detailed information can be obtained by calling GetSpriteInfo.
- */
-
-
-
- void GetSpriteLocation(short id, Rect *location)
- {
- SpriteInfoRecPtr p;
-
- p = FindSprite(id);
- if (p) {
- *location = p->animationRect;
- }
- else {
- SetRect(location, 0, 0, 0, 0);
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
- /*
- This procedure enables or disables collisions for a sprite based on the enable value.
- Sprites with collisions enabled can only collide with other sprites which
- have the collision attribute set to true.
- */
-
-
-
- void EnableSpriteCollisions(short id, Boolean enable)
- {
- SpriteInfoRecPtr p;
-
- p = FindSprite(id);
- if (p) {
- p->canCollide = enable;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
- /*
- This is a special purpose call which "validates" the old rectangle which ussed to
- be occupied by a sprite. Its purpose is to prevent redundant drawing from occuring
- when an specific sprite and face moves into the position previously occupied by
- an identical sprite and face.
- */
-
-
- void ValidateOldSpriteLocation(short id)
- {
- SpriteInfoRecPtr p;
-
- p = FindSprite(id);
- if (p) {
- p->oldAnimationRect.top = p->oldAnimationRect.left = p->oldAnimationRect.bottom =
- p->oldAnimationRect.right = 0;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- /*
- This call allows the programmer to specify a collision area for a sprite other than
- the sprite's own dimensions. The collision rectangle is given in the sprite's
- local coordinate system. By using this call collisions can be limited to a certain
- portion of th sprite's area.
- */
-
-
-
- void SetSpriteCollisionRect(short id, Rect *colRect)
- {
- SpriteInfoRecPtr p;
-
- p = FindSprite(id);
- if (p) {
- p->collisionRect = *colRect;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- /*
- This function returns a pointer to a sprite information record. The pointer returned
- is valid for the life of the sprite. That is until is the sprite is "killed" with
- a call to "KillSprite". The data structure returned by this call should be used mostly
- for read-only purposes. Altering values in the data structure could result in
- animation errors.
- */
-
-
-
- SpriteInfoRecPtr GetSpriteInfo(short id)
- {
- SpriteInfoRecPtr p;
-
- p = FindSprite(id);
- if (p)
- return(p);
- return(0L);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- /*
- This procedure destroys the graphics world used by the sprite with the given id
- if such sprite is not currently sharing a graphics world with another sprite.
- If the sprite is currently in the animaton screen its area is recorded so it
- can be updated as soon as possible by the Sprite Manager.
- */
-
-
-
- void KillSprite(short id)
- {
- SpriteInfoRecPtr p, p2, twin1, twin2;
- register short counter;
-
- for (counter = 0; counter < 3; counter++) {
- if (counter == 0)
- p = Sprite_Mgr_Globals->normSprites;
- if (counter == 1)
- p = Sprite_Mgr_Globals->backSprites;
- if (counter == 2)
- p = Sprite_Mgr_Globals->foreSprites;
- if (p) {
- if (p->id == id) {
- if (counter == 0)
- Sprite_Mgr_Globals->normSprites = (SpriteInfoRecPtr) p->nextSprite;
- if (counter == 1)
- Sprite_Mgr_Globals->backSprites = (SpriteInfoRecPtr) p->nextSprite;
- if (counter == 2)
- Sprite_Mgr_Globals->foreSprites = (SpriteInfoRecPtr) p->nextSprite;
- if (p->sharedWorld) {
- p->sharedWorld = false; // mark as unshared so FindTwin wont give us ourselves
- twin1 = FindTwinSprite(p->pictID); // find a twin
- if (!twin1)
- DisposeGWorld(p->spriteWorld); // no twins ! weird..
- else {
- twin1->sharedWorld = false; // disable this one temporarily
- twin2 = FindTwinSprite(p->pictID); // are there any more ?
- if (twin2)
- twin1->sharedWorld = true; // restore shared status since there are more sharing
- }
- }
- else {
- DisposeGWorld(p->spriteWorld);
- }
- DisposPtr((Ptr) p);
- return;
- }
- p2 = p;
- p = (SpriteInfoRecPtr) p->nextSprite;
- while (p) {
- if (p->id == id) {
- if (p->sharedWorld) {
- p->sharedWorld = false; // mark as unshared so FindTwin wont give us ourselves
- twin1 = FindTwinSprite(p->pictID); // find a twin
- if (!twin1)
- DisposeGWorld(p->spriteWorld); // no twins ! weird..
- else {
- twin1->sharedWorld = false; // disable this one temporarily
- twin2 = FindTwinSprite(p->pictID); // are there any more ?
- if (twin2)
- twin1->sharedWorld = true; // restore shared status since there are more sharing
- }
- }
- else {
- DisposeGWorld(p->spriteWorld);
- }
- p2->nextSprite = p->nextSprite;
- DisposPtr((Ptr) p);
- return;
- }
- p2 = p;
- p = (SpriteInfoRecPtr) p->nextSprite;
- }
- }
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- /*
- This routine activates the animation world so that animation will occur the next
- time DoAnimation is called. The deafult state after calling NewAnimation is to have
- the animation world inactive. All applications other than the current one are hidden
- so that the processing time is dedicated to the animation application.
- */
-
-
-
- void ActivateAnimation(void)
- {
- Sprite_Mgr_Globals->active = true;
- }
-
-
-
-
-
-
-
-
-
-
-
-
- /*
- This routine prevents any animation from ocurring by deactivating the animation
- world. This is the deafult state after calling NewAnimation. This procedure should
- be called when the animation is to be suspended. It also enabled all other applications
- so that the user can swith applications.
- */
-
-
- void DeactivateAnimation(void)
- {
- Sprite_Mgr_Globals->active = true;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- /*
- This is the main driver for the animation. If the parameter update is set to
- true then the animation world is simply redrawn. Call DoAnimation with update
- set to true when you receive an update event. When an update event occurs the
- application must bracket this call with BeginUpdate and EndUpdate and any
- application specific drawing ouside the animation area must be redrawn as well.
- When update is set to false this procedure animates the animation world by doing
- several things.
-
- 1) Go trough the backgrounds updating the animation area as nessesary.
- 2) Detect sprite collisions and calling collision procedures if nessesary.
- 3) Check the tick counters and calling the tickle procedures if any.
- 4) Updating automatic tickling sprites.
- 5) Drawing any sprites that have changed their face.
- 6) Updating foregounds.
- 7) Updating foreground sprites that have changed.
- */
-
-
- void DoAnimation(Boolean update)
- {
- GrafPtr g1, g2;
- Rect sRect;
- register short counter, total;
- register Rect *boxPtr;
- KeyMap keys;
-
- if (update) {
- g1 = (GrafPtr) Sprite_Mgr_Globals->animationGWorld;
- g2 = (GrafPtr) Sprite_Mgr_Globals->animationWindow;
- sRect = Sprite_Mgr_Globals->animationRect;
- Sprite_Mgr_Globals->task.inVBL = 0;
- while (Sprite_Mgr_Globals->task.inVBL == 0)
- ;
- CopyBits(&(g1->portBits), &(g2->portBits), &sRect, &sRect, srcCopy, 0L);
- return;
- }
- if (Sprite_Mgr_Globals->active == false)
- return;
- Sprite_Mgr_Globals->changed = false;
-
- // next: update only changed rectangles on sceneries
- // Detect collisions
-
-
- do {
- Sprite_Mgr_Globals->redoCheck = false;
- CheckChangedScenery(Sprite_Mgr_Globals->backgrounds); // backgrounds
- CheckChangedSprite(Sprite_Mgr_Globals->backSprites); // back sprites
- CheckChangedSprite(Sprite_Mgr_Globals->normSprites); // sprites
- CheckChangedScenery(Sprite_Mgr_Globals->foregrounds); // foregrounds
- CheckChangedSprite(Sprite_Mgr_Globals->foreSprites); // fore sprites
- } while (Sprite_Mgr_Globals->redoCheck);
-
- Sprite_Mgr_Globals->updateRects = 0; // nothing to update
-
- UpdateScenery(Sprite_Mgr_Globals->backgrounds); // changed backgrounds
- UpdateSprite(Sprite_Mgr_Globals->backSprites);
- UpdateSprite(Sprite_Mgr_Globals->normSprites); // changed sprites
- UpdateScenery(Sprite_Mgr_Globals->foregrounds); // changed foregrounds
- UpdateSprite(Sprite_Mgr_Globals->foreSprites);
-
- if (Sprite_Mgr_Globals->changed == false)
- return;
- g1 = (GrafPtr) Sprite_Mgr_Globals->animationGWorld;
- g2 = (GrafPtr) Sprite_Mgr_Globals->animationWindow;
-
- GetKeys(&keys[0]);
- if ((keys[1] & 0x4) == 0)
- Sprite_Mgr_Globals->updateRects = kMaxUR;
- if (Sprite_Mgr_Globals->updateRects == kMaxUR) { // update full screen
- sRect = Sprite_Mgr_Globals->animationRect;
- Sprite_Mgr_Globals->task.inVBL = 0;
- while (Sprite_Mgr_Globals->task.inVBL == 0)
- ;
- CopyBits(&(g1->portBits), &(g2->portBits), &sRect, &sRect, srcCopy, 0L);
- }
- else {
- total = Sprite_Mgr_Globals->updateRects;
- boxPtr = &(Sprite_Mgr_Globals->changedRect[0]);
- for (counter = 0; counter < total; counter++) {
- Sprite_Mgr_Globals->task.inVBL = 0;
- while (Sprite_Mgr_Globals->task.inVBL == 0)
- ;
- CopyBits(&(g1->portBits), &(g2->portBits), boxPtr, boxPtr, srcCopy, 0L);
- boxPtr++;
- }
- Sprite_Mgr_Globals->updateRects = 0;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- /*
- This procedure changes the current animation pallete used in the animation world
- to the new color table.
- */
-
-
-
- void SetNewAnimationPallete(CTabHandle cTable)
- {
- GDHandle dev;
-
- dev = Sprite_Mgr_Globals->deviceUsed;
- cTable = (**(**dev).gdPMap).pmTable;
- (**(**dev).gdPMap).pmTable = cTable;
- DisposHandle((Handle) cTable);
- GDeviceChanged(dev);
- }
-
-
-
-
-
-
-
-
-
-
- /************************************************************************************
-
- P R I V A T E R O U T I N E S
-
- *************************************************************************************/
-
-
-
- /*
- This is the common routine to create sceneries, we use this routine because we want
- to make things more readable for the programmer by providing "specialized" routines
- that allow them to distinguish between foregrounds and backgrounds.
- The basic process is to create the scenery data structure, fill in the default values,
- create the graphics world, load the picture and copy it into the g world, then
- the scenery data structure is inserted in the right place.
- I suppose that later on we could insert them in the linked list in their priority
- order.
- */
-
-
- short NewScenery(short pictID, short drawOrder, short copyMode, Rect *animationRect,
- short id, Boolean back)
- {
- SceneryInfoRecPtr sc, sc2, sc3;
- short err;
- PicHandle picH;
- Rect box;
- GWorldPtr world;
- CGrafPtr CsavePort;
- GDHandle gd;
- PixMapHandle pixH;
-
- sc = (SceneryInfoRecPtr) NewPtrClear(sizeof(SceneryInfoRec));
- if (!sc)
- return(0);
- sc->id = id;
- sc->pictID = pictID;
- sc->drawOrder = drawOrder;
- sc->copyMode = copyMode;
- sc->animationRect = *animationRect;
- sc->hidden = false;
- sc->changed = true;
- sc->shared = false;
- sc2 = FindTwinScenery(pictID);
- if (sc2) {
- sc->shared = true;
- sc2->shared = true;
- sc->sceneryWorld = sc2->sceneryWorld;
- sc->sceneryRect = sc2->sceneryRect;
- }
- else {
- picH = GetPicture(pictID);
- if (!picH) {
- DisposPtr((Ptr) sc);
- return(0);
- }
- LoadResource((Handle) picH);
- HLock((Handle) picH);
- box = (**picH).picFrame;
- box.right = box.right - box.left;
- box.bottom = box.bottom - box.top;
- box.top = box.left = 0;
- sc->sceneryRect = box;
- GetGWorld(&CsavePort, &gd);
- err = NewGWorld( &world, desiredPixSize, &box, 0L, 0L, 0L); // (long) useTempMem);
- if (err || (world->portPixMap == 0L)) {
- ReleaseResource((Handle) picH);
- DisposPtr((Ptr) sc);
- return(0);
- }
- pixH = world->portPixMap;
- HLock((Handle) pixH);
- LockPixels(pixH);
- NoPurgePixels(pixH);
- SetGWorld(world, 0L);
- sc->sceneryWorld = world;
- DrawPicture(picH, &box);
- ReleaseResource((Handle) picH);
- SetGWorld(CsavePort, gd);
- }
- if (back)
- sc2 = Sprite_Mgr_Globals->backgrounds;
- else
- sc2 = Sprite_Mgr_Globals->foregrounds;
- if (sc2->id > id) {
- if (back)
- Sprite_Mgr_Globals->backgrounds = sc;
- else
- Sprite_Mgr_Globals->foregrounds = sc;
- sc->nextScenery = (Ptr) sc2;
- return(id);
- }
- else {
- if (back)
- sc3 = sc2 = Sprite_Mgr_Globals->backgrounds;
- else
- sc3 = sc2 = Sprite_Mgr_Globals->foregrounds;
- while (sc2 && (sc2->id < id)) {
- sc3 = sc2;
- sc2 = (SceneryInfoRecPtr) sc2->nextScenery;
- }
- if (sc2) {
- sc3->nextScenery = (Ptr) sc;
- sc->nextScenery = (Ptr) sc2;
- }
- else {
- sc3->nextScenery = (Ptr) sc;
- }
- }
- return(id);
- }
-
-
-
-
-
-
-
-
-
-
-
-
- /*
- This is the common routine to create sprites, we use this routine because we want
- to make things more readable for the programmer by providing "specialized" routines
- that allow them to distinguish between foreground, normal and background sprites.
- The basic process is to create the sprite data structure, fill in the default values,
- create the graphics world, load the pictures and copy them into the g world, then
- the sprite data structure is inserted in the right place.
- I suppose that later on we could insert them in the linked list in their priority
- order.
- */
-
-
-
- short SMgrNewSprite(short pictID, short totalPicts, short copyMode,
- ProcPtr spriteProc, long ProcTicks, short drawOrder,
- ProcPtr collisionProc, Boolean canCollide, short id, short sType)
- {
- SpriteInfoRecPtr p, p2, twin;
- short err, h, v;
- PicHandle picH;
- Rect box;
- GWorldPtr world;
- CGrafPtr CsavePort;
- GDHandle gd;
- PixMapHandle pixH;
- register short counter;
-
- p = (SpriteInfoRecPtr) NewPtrClear(sizeof(SpriteInfoRec));
- if (!p)
- return(0);
- p->id = id;
- p->pictID = pictID;
- p->drawOrder = drawOrder;
- p->copyMode = copyMode;
- p->oldAnimationRect = p->animationRect;
- p->tickWait = ProcTicks;
- p->currentFace = 1;
- p->sharedWorld = false;
- p->faces = totalPicts;
- p->tickProc = spriteProc;
- p->canCollide = canCollide;
- p->collisionProc = collisionProc;
- p->hidden = false;
- p->changed = true;
- twin = FindTwinSprite(pictID);
- if (twin) {
- twin->sharedWorld = true;
- p->spriteRect = twin->spriteRect;
- p->collisionRect = twin->collisionRect;
- p->spriteWorld = twin->spriteWorld;
- p->nextSprite = 0L;
- }
- else {
- picH = GetPicture(pictID);
- if (!picH) {
- DisposPtr((Ptr) p);
- return(0);
- }
- LoadResource((Handle) picH);
- HLock((Handle) picH);
- box = (**picH).picFrame;
- h = box.right - box.left;
- v = box.bottom - box.top;
- box.right = h; // make zero offset based
- box.bottom = v;
- box.top = box.left = 0;
- p->spriteRect = box;
- p->collisionRect = box;
- box.right *= totalPicts;
- GetGWorld(&CsavePort, &gd);
- err = NewGWorld( &world, desiredPixSize, &box, 0L, 0L, 0L); // (long) useTempMem);
- if (err || (world->portPixMap == 0L)) {
- ReleaseResource((Handle) picH);
- DisposPtr((Ptr) p);
- return(0);
- }
- pixH = world->portPixMap;
- HLock((Handle) pixH);
- LockPixels(pixH);
- NoPurgePixels(pixH);
- SetGWorld(world, 0L);
- EraseRect(&world->portRect);
- p->spriteWorld = world;
- p->nextSprite = 0L;
- for (counter = 0; counter < totalPicts; counter++) {
- picH = GetPicture(pictID + counter);
- LoadResource((Handle) picH);
- HLock((Handle) picH);
- box = (**picH).picFrame;
- box.right = box.right - box.left;
- box.bottom = box.bottom - box.top;
- box.left = box.top = 0;
- box.right += h * counter;
- box.left += h * counter;
- DrawPicture(picH, &box);
- ReleaseResource((Handle) picH);
- }
- SetGWorld(CsavePort, gd);
- }
- if (sType == 1) {
- p2 = Sprite_Mgr_Globals->backSprites;
- Sprite_Mgr_Globals->backSprites = p;
- }
- if (sType == 2) {
- p2 = Sprite_Mgr_Globals->normSprites;
- Sprite_Mgr_Globals->normSprites = p;
- }
- if (sType == 3) {
- p2 = Sprite_Mgr_Globals->foreSprites;
- Sprite_Mgr_Globals->foreSprites = p;
- }
- p->nextSprite = (Ptr) p2;
- return(id);
- }
-
-
-
-
-
-
-
-
-
-
-
- /*
- This is a common routine which is used to find a sprite by a given id, this routine
- gets called by most of the sprite interface routines that allow the programmer to
- change attributes on a sprite. The lookup priority is by sprite, then foreground
- sprite and finally background sprites. If no sprite is found we return nil.
- */
-
- SpriteInfoRecPtr FindSprite(short id)
- {
- SpriteInfoRecPtr p;
-
- p = Sprite_Mgr_Globals->normSprites;
- while (p) {
- if (p->id == id)
- return(p);
- p = (SpriteInfoRecPtr) p->nextSprite;
- }
- p = Sprite_Mgr_Globals->foreSprites;
- while (p) {
- if (p->id == id)
- return(p);
- p = (SpriteInfoRecPtr) p->nextSprite;
- }
- p = Sprite_Mgr_Globals->backSprites;
- while (p) {
- if (p->id == id)
- return(p);
- p = (SpriteInfoRecPtr) p->nextSprite;
- }
- return(0L);
- }
-
-
-
-
-
-
-
-
-
-
-
- /*
- This routine is used to find a sprite that needs to share its gworld, since it
- doesn't make sense to duplicate a gworld which is going to use the same as
- another one. This could happen in a "shotter" game for example.
- */
-
-
- SpriteInfoRecPtr FindTwinSprite(short pictID)
- {
- SpriteInfoRecPtr p;
-
- p = Sprite_Mgr_Globals->normSprites;
- while (p) {
- if (p->pictID == pictID)
- return(p);
- p = (SpriteInfoRecPtr) p->nextSprite;
- }
- p = Sprite_Mgr_Globals->foreSprites;
- while (p) {
- if (p->pictID == pictID)
- return(p);
- p = (SpriteInfoRecPtr) p->nextSprite;
- }
- p = Sprite_Mgr_Globals->backSprites;
- while (p) {
- if (p->pictID == pictID)
- return(p);
- p = (SpriteInfoRecPtr) p->nextSprite;
- }
- return(0L);
- }
-
-
-
-
-
-
-
- SceneryInfoRecPtr FindTwinScenery(short pictID)
- {
- SceneryInfoRecPtr sc;
-
- sc = Sprite_Mgr_Globals->backgrounds;
- while (sc) {
- if (sc->pictID == pictID)
- return(sc);
- sc = (SceneryInfoRecPtr) sc->nextScenery;
- }
- sc = Sprite_Mgr_Globals->foregrounds;
- while (sc) {
- if (sc->pictID == pictID)
- return(sc);
- sc = (SceneryInfoRecPtr) sc->nextScenery;
- }
- return(0L);
- }
-
-
-
-
-
-
- void CheckChangedScenery(SceneryInfoRecPtr scenery)
- {
- SceneryInfoRecPtr sc = scenery;
- Rect box, dRect;
-
- while (sc) {
- box = sc->sceneryWorld->portRect;
- if (sc->scrollTicks) {
- if (sc->nextTickCount <= TickCount()) {
- sc->scrollOffset.v += sc->autoScrollAmount.v;
- sc->scrollOffset.h += sc->autoScrollAmount.h;
- sc->nextTickCount = TickCount() + sc->scrollTicks;
- sc->changed = true;
- Sprite_Mgr_Globals->redoCheck = true;
- if (sc->scrollOffset.v >= box.bottom)
- sc->scrollOffset.v = 0;
- if (sc->scrollOffset.h >= box.right)
- sc->scrollOffset.h = 0; // wrap around...
- }
- }
- if (sc->changed && (sc->hidden == false)) {
-
- dRect = sc->animationRect;
- MarkSpriteInRect(&dRect, Sprite_Mgr_Globals->backSprites);
- MarkSpriteInRect(&dRect, Sprite_Mgr_Globals->normSprites);
- MarkSpriteInRect(&dRect, Sprite_Mgr_Globals->foreSprites);
- MarkSceneryInRect(&dRect, Sprite_Mgr_Globals->foregrounds);
- MarkSceneryInRect(&dRect, Sprite_Mgr_Globals->backgrounds);
- }
- sc = (SceneryInfoRecPtr) sc->nextScenery;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
- void CheckChangedSprite(SpriteInfoRecPtr sprite)
- {
- SpriteInfoRecPtr p = sprite;
- Rect dRect;
-
- while (p) {
- if (p->tickWait) {
- if (p->lastTick <= TickCount()) {
- p->currentFace++;
- if (p->currentFace > p->faces)
- p->currentFace = 1;
- p->lastTick = TickCount() + p->tickWait;
- p->changed = true;
- Sprite_Mgr_Globals->redoCheck = true;
- }
- }
- if (p->changed && (p->hidden == false)) {
- dRect = p->animationRect;
- MarkSceneryInRect(&dRect, Sprite_Mgr_Globals->backgrounds);
- MarkSceneryInRect(&dRect, Sprite_Mgr_Globals->foregrounds);
- MarkSpriteInRect(&dRect, Sprite_Mgr_Globals->backSprites);
- MarkSpriteInRect(&dRect, Sprite_Mgr_Globals->normSprites);
- MarkSpriteInRect(&dRect, Sprite_Mgr_Globals->foreSprites);
- if (p->oldAnimationRect.right != 0) {
- dRect = p->oldAnimationRect;
- MarkSceneryInRect(&dRect, Sprite_Mgr_Globals->backgrounds);
- MarkSceneryInRect(&dRect, Sprite_Mgr_Globals->foregrounds);
- MarkSpriteInRect(&dRect, Sprite_Mgr_Globals->backSprites);
- MarkSpriteInRect(&dRect, Sprite_Mgr_Globals->normSprites);
- MarkSpriteInRect(&dRect, Sprite_Mgr_Globals->foreSprites);
- p->oldAnimationRect.right = 0;
- }
- }
- p = (SpriteInfoRecPtr) p->nextSprite;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
- void UpdateScenery(SceneryInfoRecPtr scenery)
- {
- SceneryInfoRecPtr sc = scenery;
- Rect sRect, dRect;
- WindowPtr g1, g2;
- short h, v;
- Boolean fits;
-
- while (sc) {
- if (sc->changed && (sc->hidden == false)) {
- sc->changed = false;
- fits = true;
- Sprite_Mgr_Globals->changed = true;
-
- sRect = sc->sceneryRect;
- dRect = sc->animationRect;
- if (Sprite_Mgr_Globals->updateRects < kMaxUR) {
- Sprite_Mgr_Globals->changedRect[Sprite_Mgr_Globals->updateRects] = dRect;
- Sprite_Mgr_Globals->updateRects++;
- }
- v = dRect.bottom - dRect.top;
- h = dRect.right - dRect.left;
- if (sRect.right > h) // is destination smaller ?
- sRect.right = sRect.left + h; // make source smaller
- if (sRect.bottom > v)
- sRect.bottom = sRect.top + v;
-
- sRect.top += sc->scrollOffset.v;
- sRect.bottom += sc->scrollOffset.v; // add scroll offsets
- sRect.left += sc->scrollOffset.h;
- sRect.right += sc->scrollOffset.h;
- g1 = (GrafPtr) sc->sceneryWorld;
- g2 = (GrafPtr) Sprite_Mgr_Globals->animationGWorld;
-
- if ((sRect.bottom - sRect.top) < v)
- fits = false;
- if ((sRect.right - sRect.left) < h)
- fits = false;
- if (fits) {
- CopyBits(&(g1->portBits), &(g2->portBits), &sRect, &dRect, sc->copyMode, 0L);
- }
- else { // source has scrolled too much, so compensate
- h -= sRect.right - sRect.left;
- v -= sRect.bottom - sRect.top; // get difference
-
- dRect.right -= h; // clip to area we already have
- dRect.bottom -= v;
- sRect.right -= h;
- sRect.bottom -= v;
- CopyBits(&(g1->portBits), &(g2->portBits), &sRect, &dRect, sc->copyMode, 0L);
-
- if (h) {
- dRect.right += h; // now get residue at right
- dRect.left = dRect.right - h;
- sRect.left = sc->sceneryRect.left;
- sRect.right = sRect.left + h;
- CopyBits(&(g1->portBits), &(g2->portBits), &sRect, &dRect, sc->copyMode, 0L);
- }
- if (v) {
- dRect.bottom += v; // now get residue at bottom
- dRect.top = dRect.bottom - v;
- sRect.top = sc->sceneryRect.top;
- sRect.bottom = sRect.top + v;
- CopyBits(&(g1->portBits), &(g2->portBits), &sRect, &dRect, sc->copyMode, 0L);
- }
- }
- }
- sc = (SceneryInfoRecPtr) sc->nextScenery;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
- void UpdateSprite(SpriteInfoRecPtr sprite)
- {
- SpriteInfoRecPtr p = sprite;
- Rect sRect, dRect;
- WindowPtr g1, g2;
-
- while (p) {
- if (p->changed && (p->hidden == false)) {
- p->changed = false;
- Sprite_Mgr_Globals->changed = true;
-
- sRect = p->spriteRect;
- sRect.left = sRect.right * (p->currentFace - 1); // get the right face...
- sRect.right *= p->currentFace;
- dRect = p->animationRect;
- if (Sprite_Mgr_Globals->updateRects < kMaxUR) {
- Sprite_Mgr_Globals->changedRect[Sprite_Mgr_Globals->updateRects] = dRect;
- Sprite_Mgr_Globals->updateRects++;
- }
- g1 = (GrafPtr) p->spriteWorld;
- g2 = (GrafPtr) Sprite_Mgr_Globals->animationGWorld;
- CopyBits(&(g1->portBits), &(g2->portBits), &sRect, &dRect, p->copyMode, 0L);
- }
- p = (SpriteInfoRecPtr) p->nextSprite;
- }
- }
-
-
-
-
-
-
-
-
- void MarkSceneryInRect(Rect *box, SceneryInfoRecPtr scenery)
- {
- SceneryInfoRecPtr sc;
- Rect sRect;
- Boolean dirty;
- Point pixel;
-
- sc = scenery;
- while (sc) {
- if (sc->changed == false) {
- dirty = false;
- sRect = sc->animationRect;
-
- pixel.h = sRect.left;
- pixel.v = sRect.top;
- if (SMgrPtInRect(pixel, box))
- dirty = true;
- if (!dirty) {
- pixel.h = sRect.left;
- pixel.v = sRect.bottom;
- if (SMgrPtInRect(pixel, box))
- dirty = true;
- }
- if (!dirty) {
- pixel.h = sRect.right;
- pixel.v = sRect.bottom;
- if (SMgrPtInRect(pixel, box))
- dirty = true;
- }
- if (!dirty) {
- pixel.h = sRect.right;
- pixel.v = sRect.top;
- if (SMgrPtInRect(pixel, box))
- dirty = true;
- }
- if (!dirty) {
- if (RectIntersect(&sRect, box))
- dirty = true;
- }
- if (dirty) {
- sc->changed = true;
- Sprite_Mgr_Globals->redoCheck = true;
- }
- }
- sc = (SceneryInfoRecPtr) sc->nextScenery;
- }
- }
-
-
-
-
-
-
- void MarkSpriteInRect(Rect *box, SpriteInfoRecPtr sprite)
- {
- SpriteInfoRecPtr p = sprite;
- Rect sRect;
- Boolean dirty;
- Point pixel;
-
- while (p) {
- if (p->changed == false) {
- dirty = false;
- sRect = p->animationRect;
- pixel.h = sRect.left;
- pixel.v = sRect.top;
- if (SMgrPtInRect(pixel, box))
- dirty = true;
- if (!dirty) {
- pixel.h = sRect.left;
- pixel.v = sRect.bottom;
- if (SMgrPtInRect(pixel, box))
- dirty = true;
- }
- if (!dirty) {
- pixel.h = sRect.right;
- pixel.v = sRect.bottom;
- if (SMgrPtInRect(pixel, box))
- dirty = true;
- }
- if (!dirty) {
- pixel.h = sRect.right;
- pixel.v = sRect.top;
- if (SMgrPtInRect(pixel, box))
- dirty = true;
- }
- if (!dirty) {
- if (RectIntersect(&sRect, box))
- dirty = true;
- }
- if (dirty) {
- p->changed = true;
- Sprite_Mgr_Globals->redoCheck = true;
- }
- }
- p = (SpriteInfoRecPtr) p->nextSprite;
- }
- }
-
-
-
-
-
-
-
-
-
- void CopyGToScreen(void)
- {
- short id;
- SpriteInfoRecPtr p = 0L;
- SceneryInfoRecPtr sc = 0L;
- Boolean done = false;
- GrafPtr g1, g2;
- Rect sRect, dRect;
- short mode;
-
- DebugStr("\pSet ID?");
- id = 0;
- p = FindSprite(id);
- if (!p) {
- sc = Sprite_Mgr_Globals->backgrounds;
- while (sc && !done) {
- if (sc->id == id)
- done = true;
- else
- sc = (SceneryInfoRecPtr) sc->nextScenery;
- }
- if (!sc) {
- sc = Sprite_Mgr_Globals->foregrounds;
- while (sc && !done) {
- if (sc->id == id)
- done = true;
- else
- sc = (SceneryInfoRecPtr) sc->nextScenery;
- }
- }
- if (!done)
- return;
- }
- if (p) {
- g1 = (GrafPtr) p->spriteWorld;
- dRect = sRect = p->spriteRect;
- mode = p->copyMode;
- }
- else {
- g1 = (GrafPtr) sc->sceneryWorld;
- dRect = sRect = sc->sceneryWorld->portRect;
- mode = sc->copyMode;
- }
- g2 = (GrafPtr) Sprite_Mgr_Globals->animationWindow;
- CopyBits(&(g1->portBits), &(g2->portBits), &sRect, &dRect, mode, 0L);
-
- }
-
-
-
-
-
-
-
-
-
- Boolean SMgrPtInRect(Point pixel, Rect *box)
- {
- if (pixel.h < box->left)
- return(false);
- if (pixel.h > box->right)
- return(false);
- if (pixel.v < box->top)
- return(false);
- if (pixel.v > box->bottom)
- return(false);
- return(true);
- }
-
-
-
-
-
-
-
- Boolean RectIntersect(Rect *r, Rect *box)
- {
- Rect inter; /* register short d;
-
- d = 0;
- if ((r->left > box->left) && (r->left < box->right))
- d = r->left;
- if ((box->left > r->left) && (box->left < r->right))
- d = box->left;
- if (d == 0)
- return(false);
-
- d = 0;
- if ((r->top > box->top) && (r->top < box->bottom))
- d = r->top;
- if ((box->top > r->top) && (box->top < r->bottom))
- d = box->top;
- if (d == 0)
- return(false);
-
- d = 0;
- if ((r->right < box->right) && (r->right > box->left))
- d = r->right;
- if ((box->right < r->right) && (box->right > r->left))
- d = box->right;
- if (d == 0)
- return(false);
-
- d = 0;
- if ((r->bottom < box->bottom) && (r->bottom > box->top))
- d = r->bottom;
- if ((box->bottom < r->bottom) && (box->bottom > r->top))
- d = box->bottom;
- if (d == 0)
- return(false); */
-
- if (SectRect(r, box, &inter)) // make my own
- return(true);
- return(false);
- }
-
-
-